package ru.housewife.form;

import ru.housewife.cache.CacheManager;
import ru.housewife.model.CookingDishRecipe;
import ru.housewife.model.EatingMenu;
import ru.housewife.model.EatingMenuDishRecipe;
import ru.housewife.model.EatingType;

import java.util.*;

/**
 * Form object for
 * @see ru.housewife.model.EatingMenu
 *
 * @author Alexander Troshanin
 */
public class EatingMenuForm extends AbstractFormObject<EatingMenuForm> implements Comparable<EatingMenuForm> {

    private long id;

    private EatingType eatingType = EatingType.BREAKFAST;

    private UserForm user;

    private UsersTableForm usersTable;

    private DayMenuForm dayMenu;

    private Map<Long, EatingMenuDishRecipeForm> eatingMenuRecipesByRecipeIds;

    private Map<Long, EatingMenuDishRecipeForm> eatingMenuRecipes;

    private List<EatingMenuDishRecipeForm> eatingMenuRecipesSortedCache;

    public EatingMenuForm() {
    }

    public EatingMenuForm(DayMenuForm dayMenu, EatingMenu em) {
        this.user = dayMenu.getUser();
        this.usersTable = dayMenu.getUsersTable();
        this.dayMenu = dayMenu;
        id = em.getId();
        eatingType = em.getEatingType();

        eatingMenuRecipesByRecipeIds = new HashMap<Long, EatingMenuDishRecipeForm>();
        eatingMenuRecipes = new HashMap<Long, EatingMenuDishRecipeForm>();
        for (EatingMenuDishRecipe eatingMenuRecipe : em.getEatingMenuRecipes()) {
            CookingDishRecipe recipe = eatingMenuRecipe.getRecipe();
            UserForm.UsersRecipe userRecipe = null;
            CookingDishRecipeForm recipeForm;
            if (recipe.isCommonRecipe()) {
                recipeForm = CacheManager.getInstance().getCookingDishRecipeForm(recipe.getId());
                if (recipeForm == null) {
                    // TODO: ALARM WARN...
                    continue;
                }
            } else {
                userRecipe = user.getUserRecipe(recipe.getId());
                recipeForm = userRecipe != null ? userRecipe.getRecipe() : null;
                if (recipeForm == null) {
                    // TODO: ALARM WARN...
                    //continue;
                    recipeForm = new CookingDishRecipeForm(recipe);
                }
            }
            EatingMenuDishRecipeForm eatingMenuRecipeForm = new EatingMenuDishRecipeForm(eatingMenuRecipe.getId(), this, recipeForm);
            eatingMenuRecipeForm.setCount(eatingMenuRecipe.getCount());
            eatingMenuRecipes.put(eatingMenuRecipeForm.getId(), eatingMenuRecipeForm);
            eatingMenuRecipesByRecipeIds.put(eatingMenuRecipeForm.getRecipe().getId(), eatingMenuRecipeForm);
            if (userRecipe != null) {
                userRecipe.getEatingMenuRecipes().put(eatingMenuRecipeForm.getId(), eatingMenuRecipeForm);
            }
        }
        eatingMenuRecipesSortedCache = generateSortedCache(eatingMenuRecipes);
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public EatingType getEatingType() {
        return eatingType;
    }

    public void setEatingType(EatingType eatingType) {
        this.eatingType = eatingType;
    }

    public DayMenuForm getDayMenu() {
        return dayMenu;
    }

    public void setDayMenu(DayMenuForm dayMenu) {
        this.dayMenu = dayMenu;
    }

/*
    public List<CookingDishRecipeForm> getDishRecipes() {
        return Collections.unmodifiableList(dishRecipesSortedCache);
    }

    public CookingDishRecipeForm getDishRecipe(long dishRecipeId) {
        return dishRecipes.get(dishRecipeId);
    }

    public void addDishRecipe(CookingDishRecipeForm dishRecipeForm) {
        dishRecipes.put(dishRecipeForm.getId(), dishRecipeForm);
        generateSortedCache(dishRecipesSortedCache, dishRecipes);
    }

    public void removeDishRecipe(long dishRecipeId) {
        dishRecipes.remove(dishRecipeId);
        generateSortedCache(dishRecipesSortedCache, dishRecipes);
    }
*/

    public List<EatingMenuDishRecipeForm> getEatingMenuRecipes() {
        return Collections.unmodifiableList(eatingMenuRecipesSortedCache);
    }

    public EatingMenuDishRecipeForm getEatingMenuRecipe(long eatingMenuRecipeId) {
        return eatingMenuRecipes.get(eatingMenuRecipeId);
    }

    public EatingMenuDishRecipeForm getEatingMenuRecipeByRecipeId(long recipeId) {
        return eatingMenuRecipesByRecipeIds.get(recipeId);
    }

    public void addEatingMenuRecipe(EatingMenuDishRecipeForm eatingMenuRecipeForm) {
        eatingMenuRecipes.put(eatingMenuRecipeForm.getId(), eatingMenuRecipeForm);
        eatingMenuRecipesByRecipeIds.put(eatingMenuRecipeForm.getRecipe().getId(), eatingMenuRecipeForm);
        generateSortedCache(eatingMenuRecipesSortedCache, eatingMenuRecipes);

        UserForm.UsersRecipe userRecipe = user.getUserRecipe(eatingMenuRecipeForm.getRecipe().getId());
        if (userRecipe != null) {
            userRecipe.getEatingMenuRecipes().put(eatingMenuRecipeForm.getId(), eatingMenuRecipeForm);
        }

        user.addRecipesWaresToUsersWares(eatingMenuRecipeForm.getRecipe());
    }

    public void removeEatingMenuRecipe(long eatingMenuRecipeId) {
        EatingMenuDishRecipeForm eatingMenuRecipeForm = eatingMenuRecipes.remove(eatingMenuRecipeId);
        if (eatingMenuRecipeForm != null) {
            eatingMenuRecipesByRecipeIds.remove(eatingMenuRecipeForm.getRecipe().getId());

            UserForm.UsersRecipe userRecipe = user.getUserRecipe(eatingMenuRecipeForm.getRecipe().getId());
            if (userRecipe != null) {
                userRecipe.getEatingMenuRecipes().remove(eatingMenuRecipeId);
            }
            user.removeRecipesWaresFromUsersWares(eatingMenuRecipeForm.getRecipe());

            generateSortedCache(eatingMenuRecipesSortedCache, eatingMenuRecipes);
        }

    }

    public UserForm getUser() {
        return user;
    }

    @Override
    public int compareTo(EatingMenuForm other) {
        int d1 = this.eatingType.ordinal() - other.eatingType.ordinal();
        return d1 != 0 ? d1 : (int) (this.id - other.id);
    }

    @Override
    public void updateFieldsFromSrcForm(EatingMenuForm srcForm) {
        // TODO: implement it
    }
}
